#include "TypeUtils.h"
#include "Type.h"
#include "PointerType.h"

CObjectPtrTypeGeneralized *WH::FindOrCreateObjectPtrType(CClass *Class)
{
    auto Found= reinterpret_cast<CGenericInfo*>( CSharedObjectPtrType::GetStaticType()
            ->GenericInfo)
        ->GenericMap.Find({Class});
    
    if(Found)
    {
        return (CObjectPtrTypeGeneralized *)*Found;
    }

    auto Ret=new CObjectPtrTypeGeneralized(Class);
    return Ret ;
}

CWeakObjectPtrTypeGeneralized *WH::FindOrCreateWeakObjectPtrType(CClass *Class)
{
    auto Found= reinterpret_cast<CGenericInfo*>( CWeakObjectPtrType::GetStaticType()
            ->GenericInfo)
        ->GenericMap.Find({Class});
    
    if(Found)
    {
        return (CWeakObjectPtrTypeGeneralized*)*Found;
    }

    auto Ret=new CWeakObjectPtrTypeGeneralized(Class);
    return Ret ;
}

CType *WH::FindOrCreateVectorType(CType *ValueType)
{
    auto Found= reinterpret_cast<CGenericInfo*>(CTVectorType::GetStaticType()->GenericInfo)
        ->GenericMap.Find({ValueType});

    if(Found)
    {
        return *Found;
    }
    
    auto Ret=new CTVectorGeneralized(ValueType);
    return Ret;
}

CFunctionTypeGeneralized *WH::FindOrCreateFunctionType(const SDecoratedType &ReturnType, const TVector<SDecoratedType> &ParameterTypes)
{
    CFunctionTypeGeneralized* FunctionType =  CFunctionType::FindFunctionType(ReturnType
        ,ParameterTypes);
    if(!FunctionType)
    {
        FunctionType = new CFunctionTypeGeneralized(
             ReturnType
            ,ParameterTypes
            );
    }

    return FunctionType;    
}

CScriptDelegateGenerialized *WH::FindOrCreateScriptDelegateType(CFunctionTypeGeneralized *FunctionType)
{
    TVector<CType*> Args;
    Args.Add(FunctionType->GetReturnType().BasicType);
    for(auto& Arg:FunctionType->GetParameterTypes())
    {
        Args.Add(Arg.BasicType);
    }

    auto Found= reinterpret_cast<CGenericInfo*>(CScriptDelegateType::GetStaticType()->GenericInfo)
        ->GenericMap.Find(Args);

    if(Found)
    {
        return (CScriptDelegateGenerialized*)*Found;
    }

    auto Ret=new CScriptDelegateGenerialized(FunctionType);
    return Ret;
}

CType *WH::FindOrCreateWidgetAttributeType(CType *ValueType)
{
    CType* Found=CWidgetAttributeType::FindAttributeType(ValueType);

    if(Found)
    {
        return Found;
    }   

    //create function type
    CFunctionTypeGeneralized* FunctionType =  CFunctionType::FindFunctionType(ValueType,{});

    if(!FunctionType)
    {
        FunctionType = new CFunctionTypeGeneralized(
            ValueType
            ,{}
            );
    }

    //create delegate type
    CScriptDelegateGenerialized* DelegateType = FindOrCreateScriptDelegateType(FunctionType);

    auto Ret=new CWidgetAttributeTypeGeneralized(
        ValueType
        ,FunctionType
        ,DelegateType
        );

    return Ret;
}

WHENGINE_API CPointerGeneralized *WH::FindOrCreatePointerType(CType *ValueType)
{
    auto Found =  CPointerType::FindPointerType(ValueType);

    if(Found)
    {
        return Found;
    }

    auto Ret=new CPointerGeneralized(ValueType);

    return Ret;
}
